<template>
  <a-form
    :form="form"
    :label-col="{ span: 3 }"
    class="form-section"
    @submit="handleSubmitConnect"
  >
    <!-- 数据库类型 -->
    <a-form-item
      label="数据库类型"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      :help="databaseConfigValidateMessage"
    >
      <a-radio-group
        v-model="selectedDatabaseType"
        @change="changeDatabaseType"
      >
        <a-radio-button
          v-for="element in databaseButtonImg"
          :key="element['name']"
          class="select-database-type"
          :value="element['name']"
        >
          <img
            :src="element.logo"
            :alt="element['name']"
            style="height: 50px; width: 78px;"
          />
        </a-radio-button>
      </a-radio-group>
    </a-form-item>
    <!-- 服务器 -->
    <a-form-item
      label="服务器"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      has-feedback
      class="form-item-content-width-480"
    >
      <a-input
        v-decorator="[
          'server',
          {
            rules: [{ required: true, message: '请填写服务器!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        class="form-row-input-480"
        size="small"
        placeholder="请填写"
        @change="changeDatabaseConfig"
      >
      </a-input>
    </a-form-item>
    <!-- 端口 -->
    <a-form-item
      label="端口"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      has-feedback
      class="form-item-content-width-480"
    >
      <a-input
        v-decorator="[
          'port',
          {
            rules: [{ required: true, message: '请填写端口!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        class="form-row-input-480"
        size="small"
        placeholder="请填写"
        @change="changeDatabaseConfig"
      >
      </a-input>
      <br />
    </a-form-item>
    <!-- 服务名或SID radio -->
    <a-form-item
      v-if="selectedDatabaseType === databaseMapping.oracle"
      label="服务名或SID"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      class="form-item-content-width-480"
    >
      <a-radio-group
        v-decorator="[
          'connectType',
          {
            rules: [{ required: true, message: '服务名或SID!' }],
            validateTrigger: ['blur', 'change'],
            initialValue: 'servicename',
          },
        ]"
        style="margin-left: 6px;"
        @change="changeDatabaseConfig"
      >
        <a-radio class="radio-container" value="servicename">服务名</a-radio>
        <a-radio class="radio-container" value="sid">SID </a-radio>
      </a-radio-group>
    </a-form-item>
    <!-- 服务名或SID input -->
    <a-form-item
      v-if="selectedDatabaseType === databaseMapping.oracle"
      label=" "
      :label-col="{ span: 3 }"
      :label-align="'left'"
      :colon="false"
      has-feedback
      class="form-item-content-width-480 validate-required-not-before"
    >
      <a-input
        v-decorator="[
          'connectValue',
          {
            rules: [{ required: true, message: '请填写服务名或SID!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        class="col-container"
        size="small"
        style="width: 480px;"
        placeholder="请填写"
        @change="changeDatabaseConfig"
      >
      </a-input>
    </a-form-item>
    <!-- 数据库账号 -->
    <a-form-item
      label="数据库账号"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      has-feedback
      class="form-item-content-width-480"
    >
      <a-input
        v-decorator="[
          'user',
          {
            rules: [{ required: true, message: '请填写用户名!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        class="form-row-input-480"
        size="small"
        placeholder="请填写"
        @change="changeDatabaseConfig"
      >
      </a-input>
    </a-form-item>
    <!-- 数据库密码 -->
    <a-form-item
      label="数据库密码"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      has-feedback
      class="form-item-content-width-480"
    >
      <a-input
        v-decorator="[
          'password',
          {
            rules: [{ required: true, message: '请填写密码!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        class="form-row-input-480 col-container-oracle"
        size="small"
        type="password"
        placeholder="请填写"
        @change="changeDatabaseConfig"
      >
      </a-input>
    </a-form-item>
    <!-- 连接测试 button -->
    <a-form-item
      label=" "
      :label-col="{ span: 3 }"
      :label-align="'left'"
      :colon="false"
      class="form-item-content-width-480"
    >
      <div class="col-container testing">
        <a-button
          class="testing-database-button"
          style="height: 28px; width: 81px;"
          html-type="submit"
        >
          连接测试
        </a-button>
        <span v-if="testState !== 'BEFORE_TEST'" class="testing-status">
          <a-spin v-if="testState === 'TESTING'" />
          <span
            v-else-if="testState === 'TEST_SUCCEED'"
            style="color: #78c06e;"
          >
            <a-icon
              type="check-circle"
              style="color: #78c06e;"
              theme="filled"
            />
            连接成功
          </span>
          <span v-else>
            <a-icon type="close-circle" theme="filled" />
            连接失败
            <a-button type="link" html-type="submit">重新测试</a-button>
          </span>
        </span>
      </div>
    </a-form-item>
    <!-- 选择数据库 连接成功显示 -->
    <a-form-item
      v-if="testState === 'TEST_SUCCEED'"
      :label-col="{ span: 3 }"
      :label-align="'left'"
      label="数据库（D）"
      class="form-item-content-width-480"
    >
      <a-select
        v-decorator="[
          'databaseName',
          {
            rules: [{ required: true, message: '请选择数据库!' }],
            validateTrigger: ['blur', 'change'],
          },
        ]"
        placeholder="请选择"
        class="col-container"
        style="width: 480px;"
        size="small"
        @change="changeSelectedDatabase"
      >
        <a-select-option
          v-for="option in databaseOptions"
          :key="option"
          :value="option"
        >
          {{ option }}
        </a-select-option>
      </a-select>
    </a-form-item>
    <!-- 选择导入数据 -->
    <a-form-item
      v-if="
        testState === 'TEST_SUCCEED' &&
        selectedDatabase &&
        databaseTables &&
        databaseTables.length > 0
      "
      label="选择导入数据"
      :label-align="'left'"
      :label-col="{ span: 3 }"
      class="form-item-content-width-480"
    >
      <a-select
        v-decorator="[
          'tables',
          {
            rules: [{ required: true, message: '请选择导入的数据表!' }],
          },
        ]"
        mode="multiple"
        placeholder="请选择"
        class="col-container"
        style="width: 480px;"
        size="small"
        @change="changeSelectTables"
      >
        <a-select-option
          v-for="table in databaseTables"
          :key="table"
          :value="table"
          >{{ table }}
        </a-select-option>
      </a-select>
    </a-form-item>
    <!-- 选择分类 -->
    <a-form-item
      label="选择文件夹"
      :label-col="{ span: 8 }"
      :label-align="'left'"
      class="form-item-content-width-285"
    >
      <a-select
        v-decorator="[
          'categoryId',
          {
            rules: [{ required: true, message: '请选择文件夹!' }],
            validateTrigger: ['blur', 'change'],
            initialValue: selectedCategoryId,
          },
        ]"
        placeholder="请选择"
        class="select-box"
        size="small"
        style="width: 316px;"
        @change="selectedCategoryIdChanged"
      >
        <a-select-option
          v-for="category in categorySelectOptions"
          :key="category.categoryId"
          :value="category.categoryId"
          >{{ category.categoryName }}
        </a-select-option>
      </a-select>
    </a-form-item>
  </a-form>
</template>

<script lang="ts">
/**
 * modal of testing database
 * @author Jinhui Hou
 */
import { Component, Prop } from 'vue-property-decorator'
import DataStore, { DatabaseTestState } from '@/store/modules/data'
import UploadDataMixin from '@/components/data/basic-information/upload-data-mixin'
import DataUploadStore from '@/store/modules/data-upload'
import moment from 'moment'

// 数据库默认配置
const defaultConfig = {
  databaseName: '',
  databaseType: '',
  password: '',
  port: '',
  server: '',
  tableName: '',
  user: '',
}

@Component
export default class DatabaseDataForm extends UploadDataMixin {
  @Prop({ type: Array, default: () => [] }) dataImages!: any[]
  private form: any
  private selectedDatabaseType: string = 'mysql' // 选择的数据库类型
  private selectedDatabase: string = '' // 选择的数据库

  private databaseMapping = {
    mysql: 'MySql',
    oracle: 'oracle',
  }
  private databaseConfigValidateMessage: string = ''
  // 数据库连接状态
  public get testState() {
    return DataUploadStore.testState
  }
  // 该服务器下所有库可供选择
  public get databaseOptions() {
    return DataUploadStore.databaseOptions
  }
  // 数据库的所有表
  public get databaseTables() {
    return DataUploadStore.databaseTables
  }

  public get selectedDatasetInfo() {
    return DataStore.selectedDatasetInfo
  }

  public get dataConfig() {
    if (this.selectedDatasetInfo && this.selectedDatasetInfo.dataConfig) {
      return this.selectedDatasetInfo.dataConfig
    }
    return defaultConfig
  }
  // 脱敏配置
  public get haveSetDesensitization() {
    return DataUploadStore.haveSetDesensitization
  }
  // 数据库导入时记录的语义，按照表名进行划分
  public get databaseHeadSemantic() {
    return DataUploadStore.databaseHeadSemantic
  }

  public beforeMount() {
    this.form = this.$form.createForm(this, { name: 'database_form' })
    DataUploadStore.setTestState(DatabaseTestState.BEFORE_TEST)
    this.selectedDatabase = ''
  }

  // 数据库类型 img 选择项
  public get databaseButtonImg() {
    const result: any[] = []
    this.dataImages.forEach((element: any) => {
      if (element.type !== 'http') {
        result.push(element)
      }
    })
    return result
  }

  /**
   * 修改数据库类型
   */
  public changeDatabaseType($event: any) {
    this.selectedDatabaseType = $event.target.value
    this.changeDatabaseConfig() // 复用修改参数的 func
  }

  /**
   * 编辑数据库连接信息， 恢复到连接前的状态
   */
  public changeDatabaseConfig() {
    DataUploadStore.setTestState(DatabaseTestState.BEFORE_TEST)
    DataUploadStore.setSelectedTables([])
    this.form.setFieldsValue({ tables: [] })
    DataUploadStore.setDatabaseHeadSemantic({}) // 初始化语义
    DataUploadStore.setDataInformationCollapsePanelShow(false) // 关闭 数据信息折叠框
    DataUploadStore.setSelectedTableData(null) // 清除预览数据
  }

  /**
   * 连接数据库
   * @param event
   */
  public handleSubmitConnect(event: Event) {
    event.preventDefault()
    this.$nextTick(() => {
      this.form.validateFields(async (error: Error, values: any) => {
        if (!error) {
          const { connectType, connectValue } = values
          let passData: any = {
            databaseType: this.selectedDatabaseType,
            server: values.server,
            port: values.port,
            user: values.user,
            password: values.password,
          }
          if (this.selectedDatabaseType === this.databaseMapping.oracle) {
            passData = {
              ...passData,
              connectType,
              connectValue,
            }
          }
          DataUploadStore.setDatabaseConfig(passData)
          await DataUploadStore.testConnection(passData)
        } else {
          console.log('error:', error)
        }
      })
    })
  }

  /**
   * 连接成功选择的数据库
   * @param value
   */
  public changeSelectedDatabase(value: string) {
    this.form.setFieldsValue({ databaseName: value })
    this.selectedDatabase = value
    this.importDatabase()
  }

  /**
   * 选择数据库后更新获取库的表信息
   */
  public importDatabase() {
    if (this.testState !== DatabaseTestState.TEST_SUCCEED) {
      // 还未通过测试时，点击确定会提示进行测试
      this.$message.error('请先进行数据库连接测试!')
      return
    }
    this.form.validateFields(async (error: Error) => {
      // 通过测试后，点击确定会提交相应数据，并获取所有表
      // if (!error) {
      const passData = {
        ...DataUploadStore.databaseConfig,
        databaseName: this.selectedDatabase,
      }
      DataUploadStore.setDatabaseConfig(passData)
      await DataUploadStore.queryDatabaseTables(passData)
      this.databaseConfigValidateMessage = ''
      DataUploadStore.setSelectedTables([])
      this.form.setFieldsValue({ tables: [] })
      // } else {
      console.log('error:', error)
      // }
    })
  }

  /**
   * 外部数据库 选择的数据表 变化
   */
  public changeSelectTables(values: any) {
    const openCollapsePanel: boolean = values.length > 0
    DataUploadStore.setDataInformationCollapsePanelShow(openCollapsePanel) // 打开/关闭 数据信息折叠框
    DataUploadStore.setSelectedTables(values) // 存储选择的数据库表
  }

  /**
   * 取消导入 父组件调用
   */
  public cancelImportData() {
    this.form.setFieldsValue({ tables: [] })
    DataUploadStore.setSelectedTables([]) // 存储选择的数据库表
    DataUploadStore.setHaveSetDesensitization({}) // init
  }

  /**
   * 提交
   */
  public handleSubmit() {
    this.form.validateFields(async (error: Error, values: any) => {
      if (
        !this.selectedDatabase ||
        DataUploadStore.testState !== DatabaseTestState.TEST_SUCCEED
      ) {
        this.databaseConfigValidateMessage = '请先配置数据库并进行连接测试！'
        return
      }
      if (!error) {
        const id = values.categoryId
        const tableConfigs = this.dealDatabaseData(values.tables)
        const passData = {
          categoryId: id,
          ...DataUploadStore.databaseConfig,
          importType: 'table',
          tableConfigs,
        }
        this.$emit('begin-database-upload', passData)
      } else {
        console.log('error:', error)
      }
    })
  }

  /**
   * 处理外部数据库导入 各表的配置
   * @author Jinhui Hou
   */
  public dealDatabaseData(tables: any) {
    const defaultTimingConfig = {
      beginDate: moment(new Date()),
      daysOfWeek: 'SUN',
      hourOfDay: 0,
      incrementColumn: '',
      minuteOfHour: 0,
      needSchedule: false,
      intervalOfHour: 1,
      scheduleType: 'day',
    }
    const { haveSetDesensitization, databaseHeadSemantic } = this
    const tableConfigs = tables.map((table: string) => {
      const tableColumns: any[] = []
      // 由于目前tables 是多张表的表名数组 ['table1'， 'table2'] ,
      // 列的配置 从 已经配置好的haveSetDesensitization 配置中遍历获取。
      Object.keys(haveSetDesensitization[table]).forEach((column: string) => {
        const currentColumn = haveSetDesensitization[table][column]
        const columnSemantic = databaseHeadSemantic[table][column]
        tableColumns.push({
          name: column,
          type: columnSemantic.type,
          semantic: columnSemantic.semantic || columnSemantic.recommendSemantic,
          dataLevelId: currentColumn.masking ? currentColumn.dataLevelId : null,
          dataMaskingType: currentColumn.masking
            ? currentColumn.dataMaskingType
            : null,
          importColumn: currentColumn.importColumn,
        })
      })
      const timeConfig = DataUploadStore.timingSettingMaps
        ? DataUploadStore.timingSettingMaps[table]
        : {}
      return {
        tableName: table,
        data: tableColumns,
        datasetScheduleConfig: DataUploadStore.timingSettingMaps
          ? timeConfig
          : defaultTimingConfig,
      }
    })
    return tableConfigs
  }
}
</script>
<style lang="less" scoped>
@import './data-type';

// 服务器与SID样式
.server-sid-item {
  height: 75px;

  /deep/ .ant-form-item-children-icon {
    top: 43px;
  }

  /deep/ .ant-form-explain {
    top: 43px;
  }
}

/deep/ .ant-form-item {
  margin-bottom: 10px;
}

// 定死左侧 label 宽度
/deep/ .ant-form-item-label-left {
  width: 98px;
}

// 数据库类型
.select-database-type {
  height: 52px;
  margin-right: 16px;
  padding: 0;
  width: 80px;
}

.col-container {
  border-radius: 4px;
  //margin-left: 8px;

  &.testing {
    padding-top: 2px;

    /deep/ .testing-database-button {
      padding: auto 12px;
    }

    .testing-status {
      margin-left: 20px;
    }
  }
}
</style>
